package tjs.study.notes.dotest.jvm.classload.encode;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * Created by Nicky.Tang on 2021/10/20 2:48 下午
 *
 * @since 02.12.10
 */
public class DecodeClassLoader extends ClassLoader {
    private String loaderPath;

    public DecodeClassLoader(String path) {
        loaderPath = path;
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException {
        Class<?> loadedClass = this.findLoadedClass(name);
        if (loadedClass == null) {
            try {
                // 打破双亲委派机制，优先自己加载
                loadedClass = this.findClass(name);
            } catch (ClassNotFoundException var9) {
                //java.lang等包不能由自定义的类加载器加载
                loadedClass = Class.forName(name, false, this.getParent());
            }
        }
        if (resolve) {
            this.resolveClass(loadedClass);
        }

        return loadedClass;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        File file = new File(loaderPath + "/" + name.replaceAll("\\.", "/") + ".class_encode");
        if (!file.exists()) {
            throw new ClassNotFoundException(name);
        }
        System.out.println("开始解密文件：" + file.getPath());
        int len = 0;
        byte[] data = null;
        try (FileInputStream is = new FileInputStream(file);
             ByteArrayOutputStream bos = new ByteArrayOutputStream();) {
            while ((len = is.read()) != -1) {
                // fixme 解密-二次异或运算
                bos.write(len ^ DoTestOfEncryption.ENCODE_KEY);
            }
            data = bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return defineClass(name, data, 0, data.length);
    }
}
